home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1992 July / Nautilus-3-8 / Nautilus-3-8.bin / Tools & Utilities / Techy Stuff / Development Environments ƒ / Perl 4.0.2 ƒ / cons.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-05  |  35.1 KB  |  1,431 lines

  1. /* $RCSfile: cons.c,v $$Revision: 4.0.1.2 $$Date: 91/11/05 16:15:13 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    cons.c,v $
  9.  * Revision 4.0.1.2  91/11/05  16:15:13  lwall
  10.  * patch11: debugger got confused over nested subroutine definitions
  11.  * patch11: prepared for ctype implementations that don't define isascii()
  12.  * 
  13.  * Revision 4.0.1.1  91/06/07  10:31:15  lwall
  14.  * patch4: new copyright notice
  15.  * patch4: added global modifier for pattern matches
  16.  * 
  17.  * Revision 4.0  91/03/20  01:05:51  lwall
  18.  * 4.0 baseline.
  19.  * 
  20.  */
  21.  
  22. #include "EXTERN.h"
  23. #include "perl.h"
  24. #include "perly.h"
  25.  
  26. extern char *tokename[];
  27. extern int yychar;
  28.  
  29. static int cmd_tosave();
  30. static int arg_tosave();
  31. static int spat_tosave();
  32.  
  33. static bool saw_return;
  34.  
  35. SUBR *
  36. make_sub(name,cmd)
  37. char *name;
  38. CMD *cmd;
  39. {
  40.     register SUBR *sub;
  41.     STAB *stab = stabent(name,TRUE);
  42.  
  43.     Newz(101,sub,1,SUBR);
  44.     if (stab_sub(stab)) {
  45.     if (dowarn) {
  46.         CMD *oldcurcmd = curcmd;
  47.  
  48.         if (cmd)
  49.         curcmd = cmd;
  50.         warn("Subroutine %s redefined",name);
  51.         curcmd = oldcurcmd;
  52.     }
  53.     if (stab_sub(stab)->cmd) {
  54.         cmd_free(stab_sub(stab)->cmd);
  55.         stab_sub(stab)->cmd = Nullcmd;
  56.         afree(stab_sub(stab)->tosave);
  57.     }
  58.     Safefree(stab_sub(stab));
  59.     }
  60.     stab_sub(stab) = sub;
  61.     sub->filestab = curcmd->c_filestab;
  62.     saw_return = FALSE;
  63.     tosave = anew(Nullstab);
  64.     tosave->ary_fill = 0;    /* make 1 based */
  65.     (void)cmd_tosave(cmd,FALSE);    /* this builds the tosave array */
  66.     sub->tosave = tosave;
  67.     if (saw_return) {
  68.     struct compcmd mycompblock;
  69.  
  70.     mycompblock.comp_true = cmd;
  71.     mycompblock.comp_alt = Nullcmd;
  72.     cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,Nullarg,mycompblock));
  73.     saw_return = FALSE;
  74.     cmd->c_flags |= CF_TERM;
  75.     }
  76.     sub->cmd = cmd;
  77.     if (perldb) {
  78.     STR *str;
  79.     STR *tmpstr = str_mortal(&str_undef);
  80.  
  81.     sprintf(buf,"%s:%ld",stab_val(curcmd->c_filestab)->str_ptr, subline);
  82.     str = str_make(buf,0);
  83.     str_cat(str,"-");
  84.     sprintf(buf,"%ld",(long)curcmd->c_line);
  85.     str_cat(str,buf);
  86.     name = str_get(subname);
  87.     stab_fullname(tmpstr,stab);
  88.     hstore(stab_xhash(DBsub), tmpstr->str_ptr, tmpstr->str_cur, str, 0);
  89.     }
  90.     return sub;
  91. }
  92.  
  93. SUBR *
  94. make_usub(name, ix, subaddr, filename)
  95. char *name;
  96. int ix;
  97. int (*subaddr)();
  98. char *filename;
  99. {
  100.     register SUBR *sub;
  101.     STAB *stab = stabent(name,allstabs);
  102.  
  103.     if (!stab)                /* unused function */
  104.     return Null(SUBR*);
  105.     Newz(101,sub,1,SUBR);
  106.     if (stab_sub(stab)) {
  107.     if (dowarn)
  108.         warn("Subroutine %s redefined",name);
  109.     if (stab_sub(stab)->cmd) {
  110.         cmd_free(stab_sub(stab)->cmd);
  111.         stab_sub(stab)->cmd = Nullcmd;
  112.         afree(stab_sub(stab)->tosave);
  113.     }
  114.     Safefree(stab_sub(stab));
  115.     }
  116.     stab_sub(stab) = sub;
  117.     sub->filestab = fstab(filename);
  118.     sub->usersub = subaddr;
  119.     sub->userindex = ix;
  120.     return sub;
  121. }
  122.  
  123. make_form(stab,fcmd)
  124. STAB *stab;
  125. FCMD *fcmd;
  126. {
  127.     if (stab_form(stab)) {
  128.     FCMD *tmpfcmd;
  129.     FCMD *nextfcmd;
  130.  
  131.     for (tmpfcmd = stab_form(stab); tmpfcmd; tmpfcmd = nextfcmd) {
  132.         nextfcmd = tmpfcmd->f_next;
  133.         if (tmpfcmd->f_expr)
  134.         arg_free(tmpfcmd->f_expr);
  135.         if (tmpfcmd->f_unparsed)
  136.         str_free(tmpfcmd->f_unparsed);
  137.         if (tmpfcmd->f_pre)
  138.         Safefree(tmpfcmd->f_pre);
  139.         Safefree(tmpfcmd);
  140.     }
  141.     }
  142.     stab_form(stab) = fcmd;
  143. }
  144.  
  145. CMD *
  146. block_head(tail)
  147. register CMD *tail;
  148. {
  149.     CMD *head;
  150.     register int opt;
  151.     register int last_opt = 0;
  152.     register STAB *last_stab = Nullstab;
  153.     register int count = 0;
  154.     register CMD *switchbeg = Nullcmd;
  155.  
  156.     if (tail == Nullcmd) {
  157.     return tail;
  158.     }
  159.     head = tail->c_head;
  160.  
  161.     for (tail = head; tail; tail = tail->c_next) {
  162.  
  163.     /* save one measly dereference at runtime */
  164.     if (tail->c_type == C_IF) {
  165.         if (!(tail->ucmd.ccmd.cc_alt = tail->ucmd.ccmd.cc_alt->c_next))
  166.         tail->c_flags |= CF_TERM;
  167.     }
  168.     else if (tail->c_type == C_EXPR) {
  169.         ARG *arg;
  170.  
  171.         if (tail->ucmd.acmd.ac_expr)
  172.         arg = tail->ucmd.acmd.ac_expr;
  173.         else
  174.         arg = tail->c_expr;
  175.         if (arg) {
  176.         if (arg->arg_type == O_RETURN)
  177.             tail->c_flags |= CF_TERM;
  178.         else if (arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  179.             tail->c_flags |= CF_TERM;
  180.         }
  181.     }
  182.     if (!tail->c_next)
  183.         tail->c_flags |= CF_TERM;
  184.  
  185.     if (tail->c_expr && (tail->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  186.         opt_arg(tail,1, tail->c_type == C_EXPR);
  187.  
  188.     /* now do a little optimization on case-ish structures */
  189.     switch(tail->c_flags & (CF_OPTIMIZE|CF_FIRSTNEG|CF_INVERT)) {
  190.     case CFT_ANCHOR:
  191.         if (stabent("*",FALSE)) {    /* bad assumption here!!! */
  192.         opt = 0;
  193.         break;
  194.         }
  195.         /* FALL THROUGH */
  196.     case CFT_STROP:
  197.         opt = (tail->c_flags & CF_NESURE) ? CFT_STROP : 0;
  198.         break;
  199.     case CFT_CCLASS:
  200.         opt = CFT_STROP;
  201.         break;
  202.     case CFT_NUMOP:
  203.         opt = (tail->c_slen == O_NE ? 0 : CFT_NUMOP);
  204.         if ((tail->c_flags&(CF_NESURE|CF_EQSURE)) != (CF_NESURE|CF_EQSURE))
  205.         opt = 0;
  206.         break;
  207.     default:
  208.         opt = 0;
  209.     }
  210.     if (opt && opt == last_opt && tail->c_stab == last_stab)
  211.         count++;
  212.     else {
  213.         if (count >= 3) {        /* is this the breakeven point? */
  214.         if (last_opt == CFT_NUMOP)
  215.             make_nswitch(switchbeg,count);
  216.         else
  217.             make_cswitch(switchbeg,count);
  218.         }
  219.         if (opt) {
  220.         count = 1;
  221.         switchbeg = tail;
  222.         }
  223.         else
  224.         count = 0;
  225.     }
  226.     last_opt = opt;
  227.     last_stab = tail->c_stab;
  228.     }
  229.     if (count >= 3) {        /* is this the breakeven point? */
  230.     if (last_opt == CFT_NUMOP)
  231.         make_nswitch(switchbeg,count);
  232.     else
  233.         make_cswitch(switchbeg,count);
  234.     }
  235.     return head;
  236. }
  237.  
  238. /* We've spotted a sequence of CMDs that all test the value of the same
  239.  * spat.  Thus we can insert a SWITCH in front and jump directly
  240.  * to the correct one.
  241.  */
  242. make_cswitch(head,count)
  243. register CMD *head;
  244. int count;
  245. {
  246.     register CMD *cur;
  247.     register CMD **loc;
  248.     register int i;
  249.     register int min = 255;
  250.     register int max = 0;
  251.  
  252.     /* make a new head in the exact same spot */
  253.     New(102,cur, 1, CMD);
  254. #ifdef STRUCTCOPY
  255.     *cur = *head;
  256. #else
  257.     Copy(head,cur,1,CMD);
  258. #endif
  259.     Zero(head,1,CMD);
  260.     head->c_type = C_CSWITCH;
  261.     head->c_next = cur;        /* insert new cmd at front of list */
  262.     head->c_stab = cur->c_stab;
  263.  
  264.     Newz(103,loc,258,CMD*);
  265.     loc++;                /* lie a little */
  266.     while (count--) {
  267.     if ((cur->c_flags & CF_OPTIMIZE) == CFT_CCLASS) {
  268.         for (i = 0; i <= 255; i++) {
  269.         if (!loc[i] && cur->c_short->str_ptr[i>>3] & (1 << (i&7))) {
  270.             loc[i] = cur;
  271.             if (i < min)
  272.             min = i;
  273.             if (i > max)
  274.             max = i;
  275.         }
  276.         }
  277.     }
  278.     else {
  279.         i = *cur->c_short->str_ptr & 255;
  280.         if (!loc[i]) {
  281.         loc[i] = cur;
  282.         if (i < min)
  283.             min = i;
  284.         if (i > max)
  285.             max = i;
  286.         }
  287.     }
  288.     cur = cur->c_next;
  289.     }
  290.     max++;
  291.     if (min > 0)
  292.     Copy(&loc[min],&loc[0], max - min, CMD*);
  293.     loc--;
  294.     min--;
  295.     max -= min;
  296.     for (i = 0; i <= max; i++)
  297.     if (!loc[i])
  298.         loc[i] = cur;
  299.     Renew(loc,max+1,CMD*);    /* chop it down to size */
  300.     head->ucmd.scmd.sc_offset = min;
  301.     head->ucmd.scmd.sc_max = max;
  302.     head->ucmd.scmd.sc_next = loc;
  303. }
  304.  
  305. make_nswitch(head,count)
  306. register CMD *head;
  307. int count;
  308. {
  309.     register CMD *cur = head;
  310.     register CMD **loc;
  311.     register int i;
  312.     register int min = 32767;
  313.     register int max = -32768;
  314.     int origcount = count;
  315.     double value;        /* or your money back! */
  316.     short changed;        /* so triple your money back! */
  317.  
  318.     while (count--) {
  319.     i = (int)str_gnum(cur->c_short);
  320.     value = (double)i;
  321.     if (value != cur->c_short->str_u.str_nval)
  322.         return;        /* fractional values--just forget it */
  323.     changed = i;
  324.     if (changed != i)
  325.         return;        /* too big for a short */
  326.     if (cur->c_slen == O_LE)
  327.         i++;
  328.     else if (cur->c_slen == O_GE)    /* we only do < or > here */
  329.         i--;
  330.     if (i < min)
  331.         min = i;
  332.     if (i > max)
  333.         max = i;
  334.     cur = cur->c_next;
  335.     }
  336.     count = origcount;
  337.     if (max - min > count * 2 + 10)        /* too sparse? */
  338.     return;
  339.  
  340.     /* now make a new head in the exact same spot */
  341.     New(104,cur, 1, CMD);
  342. #ifdef STRUCTCOPY
  343.     *cur = *head;
  344. #else
  345.     Copy(head,cur,1,CMD);
  346. #endif
  347.     Zero(head,1,CMD);
  348.     head->c_type = C_NSWITCH;
  349.     head->c_next = cur;        /* insert new cmd at front of list */
  350.     head->c_stab = cur->c_stab;
  351.  
  352.     Newz(105,loc, max - min + 3, CMD*);
  353.     loc++;
  354.     max -= min;
  355.     max++;
  356.     while (count--) {
  357.     i = (int)str_gnum(cur->c_short);
  358.     i -= min;
  359.     switch(cur->c_slen) {
  360.     case O_LE:
  361.         i++;
  362.     case O_LT:
  363.         for (i--; i >= -1; i--)
  364.         if (!loc[i])
  365.             loc[i] = cur;
  366.         break;
  367.     case O_GE:
  368.         i--;
  369.     case O_GT:
  370.         for (i++; i <= max; i++)
  371.         if (!loc[i])
  372.             loc[i] = cur;
  373.         break;
  374.     case O_EQ:
  375.         if (!loc[i])
  376.         loc[i] = cur;
  377.         break;
  378.     }
  379.     cur = cur->c_next;
  380.     }
  381.     loc--;
  382.     min--;
  383.     max++;
  384.     for (i = 0; i <= max; i++)
  385.     if (!loc[i])
  386.         loc[i] = cur;
  387.     head->ucmd.scmd.sc_offset = min;
  388.     head->ucmd.scmd.sc_max = max;
  389.     head->ucmd.scmd.sc_next = loc;
  390. }
  391.  
  392. CMD *
  393. append_line(head,tail)
  394. register CMD *head;
  395. register CMD *tail;
  396. {
  397.     if (tail == Nullcmd)
  398.     return head;
  399.     if (!tail->c_head)            /* make sure tail is well formed */
  400.     tail->c_head = tail;
  401.     if (head != Nullcmd) {
  402.     tail = tail->c_head;        /* get to start of tail list */
  403.     if (!head->c_head)
  404.         head->c_head = head;    /* start a new head list */
  405.     while (head->c_next) {
  406.         head->c_next->c_head = head->c_head;
  407.         head = head->c_next;    /* get to end of head list */
  408.     }
  409.     head->c_next = tail;        /* link to end of old list */
  410.     tail->c_head = head->c_head;    /* propagate head pointer */
  411.     }
  412.     while (tail->c_next) {
  413.     tail->c_next->c_head = tail->c_head;
  414.     tail = tail->c_next;
  415.     }
  416.     return tail;
  417. }
  418.  
  419. CMD *
  420. dodb(cur)
  421. CMD *cur;
  422. {
  423.     register CMD *cmd;
  424.     register CMD *head = cur->c_head;
  425.     STR *str;
  426.  
  427.     if (!head)
  428.     head = cur;
  429.     if (!head->c_line)
  430.     return cur;
  431.     str = afetch(stab_xarray(curcmd->c_filestab),(int)head->c_line,FALSE);
  432.     if (str == &str_undef || str->str_nok)
  433.     return cur;
  434.     str->str_u.str_nval = (double)head->c_line;
  435.     str->str_nok = 1;
  436.     Newz(106,cmd,1,CMD);
  437.     str_magic(str, curcmd->c_filestab, 0, Nullch, 0);
  438.     str->str_magic->str_u.str_cmd = cmd;
  439.     cmd->c_type = C_EXPR;
  440.     cmd->ucmd.acmd.ac_stab = Nullstab;
  441.     cmd->ucmd.acmd.ac_expr = Nullarg;
  442.     cmd->c_expr = make_op(O_SUBR, 2,
  443.     stab2arg(A_WORD,DBstab),
  444.     Nullarg,
  445.     Nullarg);
  446.     cmd->c_flags |= CF_COND|CF_DBSUB|CFT_D0;
  447.     cmd->c_line = head->c_line;
  448.     cmd->c_label = head->c_label;
  449.     cmd->c_filestab = curcmd->c_filestab;
  450.     cmd->c_stash = curstash;
  451.     return append_line(cmd, cur);
  452. }
  453.  
  454. CMD *
  455. make_acmd(type,stab,cond,arg)
  456. int type;
  457. STAB *stab;
  458. ARG *cond;
  459. ARG *arg;
  460. {
  461.     register CMD *cmd;
  462.  
  463.     Newz(107,cmd,1,CMD);
  464.     cmd->c_type = type;
  465.     cmd->ucmd.acmd.ac_stab = stab;
  466.     cmd->ucmd.acmd.ac_expr = arg;
  467.     cmd->c_expr = cond;
  468.     if (cond)
  469.     cmd->c_flags |= CF_COND;
  470.     if (cmdline == NOLINE)
  471.     cmd->c_line = curcmd->c_line;
  472.     else {
  473.     cmd->c_line = cmdline;
  474.     cmdline = NOLINE;
  475.     }
  476.     cmd->c_filestab = curcmd->c_filestab;
  477.     cmd->c_stash = curstash;
  478.     if (perldb)
  479.     cmd = dodb(cmd);
  480.     return cmd;
  481. }
  482.  
  483. CMD *
  484. make_ccmd(type,arg,cblock)
  485. int type;
  486. ARG *arg;
  487. struct compcmd cblock;
  488. {
  489.     register CMD *cmd;
  490.  
  491.     Newz(108,cmd, 1, CMD);
  492.     cmd->c_type = type;
  493.     cmd->c_expr = arg;
  494.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  495.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  496.     if (arg)
  497.     cmd->c_flags |= CF_COND;
  498.     if (cmdline == NOLINE)
  499.     cmd->c_line = curcmd->c_line;
  500.     else {
  501.     cmd->c_line = cmdline;
  502.     cmdline = NOLINE;
  503.     }
  504.     cmd->c_filestab = curcmd->c_filestab;
  505.     cmd->c_stash = curstash;
  506.     if (perldb)
  507.     cmd = dodb(cmd);
  508.     return cmd;
  509. }
  510.  
  511. CMD *
  512. make_icmd(type,arg,cblock)
  513. int type;
  514. ARG *arg;
  515. struct compcmd cblock;
  516. {
  517.     register CMD *cmd;
  518.     register CMD *alt;
  519.     register CMD *cur;
  520.     register CMD *head;
  521.     struct compcmd ncblock;
  522.  
  523.     Newz(109,cmd, 1, CMD);
  524.     head = cmd;
  525.     cmd->c_type = type;
  526.     cmd->c_expr = arg;
  527.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  528.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  529.     if (arg)
  530.     cmd->c_flags |= CF_COND;
  531.     if (cmdline == NOLINE)
  532.     cmd->c_line = curcmd->c_line;
  533.     else {
  534.     cmd->c_line = cmdline;
  535.     cmdline = NOLINE;
  536.     }
  537.     cmd->c_filestab = curcmd->c_filestab;
  538.     cmd->c_stash = curstash;
  539.     cur = cmd;
  540.     alt = cblock.comp_alt;
  541.     while (alt && alt->c_type == C_ELSIF) {
  542.     cur = alt;
  543.     alt = alt->ucmd.ccmd.cc_alt;
  544.     }
  545.     if (alt) {            /* a real life ELSE at the end? */
  546.     ncblock.comp_true = alt;
  547.     ncblock.comp_alt = Nullcmd;
  548.     alt = append_line(cur,make_ccmd(C_ELSE,Nullarg,ncblock));
  549.     cur->ucmd.ccmd.cc_alt = alt;
  550.     }
  551.     else
  552.     alt = cur;        /* no ELSE, so cur is proxy ELSE */
  553.  
  554.     cur = cmd;
  555.     while (cmd) {        /* now point everyone at the ELSE */
  556.     cur = cmd;
  557.     cmd = cur->ucmd.ccmd.cc_alt;
  558.     cur->c_head = head;
  559.     if (cur->c_type == C_ELSIF)
  560.         cur->c_type = C_IF;
  561.     if (cur->c_type == C_IF)
  562.         cur->ucmd.ccmd.cc_alt = alt;
  563.     if (cur == alt)
  564.         break;
  565.     cur->c_next = cmd;
  566.     }
  567.     if (perldb)
  568.     cur = dodb(cur);
  569.     return cur;
  570. }
  571.  
  572. void
  573. opt_arg(cmd,fliporflop,acmd)
  574. register CMD *cmd;
  575. int fliporflop;
  576. int acmd;
  577. {
  578.     register ARG *arg;
  579.     int opt = CFT_EVAL;
  580.     int sure = 0;
  581.     ARG *arg2;
  582.     int context = 0;    /* 0 = normal, 1 = before &&, 2 = before || */
  583.     int flp = fliporflop;
  584.  
  585.     if (!cmd)
  586.     return;
  587.     if (!(arg = cmd->c_expr)) {
  588.     cmd->c_flags &= ~CF_COND;
  589.     return;
  590.     }
  591.  
  592.     /* Can we turn && and || into if and unless? */
  593.  
  594.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM) &&
  595.       (arg->arg_type == O_AND || arg->arg_type == O_OR) ) {
  596.     dehoist(arg,1);
  597.     arg[2].arg_type &= A_MASK;    /* don't suppress eval */
  598.     dehoist(arg,2);
  599.     cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg;
  600.     cmd->c_expr = arg[1].arg_ptr.arg_arg;
  601.     if (arg->arg_type == O_OR)
  602.         cmd->c_flags ^= CF_INVERT;        /* || is like unless */
  603.     arg->arg_len = 0;
  604.     free_arg(arg);
  605.     arg = cmd->c_expr;
  606.     }
  607.  
  608.     /* Turn "if (!expr)" into "unless (expr)" */
  609.  
  610.     if (!(cmd->c_flags & CF_TERM)) {        /* unless return value wanted */
  611.     while (arg->arg_type == O_NOT) {
  612.         dehoist(arg,1);
  613.         cmd->c_flags ^= CF_INVERT;        /* flip sense of cmd */
  614.         cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */
  615.         free_arg(arg);
  616.         arg = cmd->c_expr;            /* here we go again */
  617.     }
  618.     }
  619.  
  620.     if (!arg->arg_len) {        /* sanity check */
  621.     cmd->c_flags |= opt;
  622.     return;
  623.     }
  624.  
  625.     /* for "cond .. cond" we set up for the initial check */
  626.  
  627.     if (arg->arg_type == O_FLIP)
  628.     context |= 4;
  629.  
  630.     /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */
  631.  
  632.   morecontext:
  633.     if (arg->arg_type == O_AND)
  634.     context |= 1;
  635.     else if (arg->arg_type == O_OR)
  636.     context |= 2;
  637.     if (context && (arg[flp].arg_type & A_MASK) == A_EXPR) {
  638.     arg = arg[flp].arg_ptr.arg_arg;
  639.     flp = 1;
  640.     if (arg->arg_type == O_AND || arg->arg_type == O_OR)
  641.         goto morecontext;
  642.     }
  643.     if ((context & 3) == 3)
  644.     return;
  645.  
  646.     if (arg[flp].arg_flags & (AF_PRE|AF_POST)) {
  647.     cmd->c_flags |= opt;
  648.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM)
  649.       && cmd->c_expr->arg_type == O_ITEM) {
  650.         arg[flp].arg_flags &= ~AF_POST;    /* prefer ++$foo to $foo++ */
  651.         arg[flp].arg_flags |= AF_PRE;    /*  if value not wanted */
  652.     }
  653.     return;                /* side effect, can't optimize */
  654.     }
  655.  
  656.     if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP ||
  657.       arg->arg_type == O_AND || arg->arg_type == O_OR) {
  658.     if ((arg[flp].arg_type & A_MASK) == A_SINGLE) {
  659.         opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE);
  660.         cmd->c_short = str_smake(arg[flp].arg_ptr.arg_str);
  661.         goto literal;
  662.     }
  663.     else if ((arg[flp].arg_type & A_MASK) == A_STAB ||
  664.       (arg[flp].arg_type & A_MASK) == A_LVAL) {
  665.         cmd->c_stab  = arg[flp].arg_ptr.arg_stab;
  666.         if (!context)
  667.         arg[flp].arg_ptr.arg_stab = Nullstab;
  668.         opt = CFT_REG;
  669.       literal:
  670.         if (!context) {    /* no && or ||? */
  671.         arg_free(arg);
  672.         cmd->c_expr = Nullarg;
  673.         }
  674.         if (!(context & 1))
  675.         cmd->c_flags |= CF_EQSURE;
  676.         if (!(context & 2))
  677.         cmd->c_flags |= CF_NESURE;
  678.     }
  679.     }
  680.     else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST ||
  681.          arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) {
  682.     if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  683.         (arg[2].arg_type & A_MASK) == A_SPAT &&
  684.         arg[2].arg_ptr.arg_spat->spat_short &&
  685.         (arg->arg_type == O_SUBST || arg->arg_type == O_NSUBST ||
  686.          (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_GLOBAL) == 0 )) {
  687.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  688.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_spat->spat_short);
  689.         cmd->c_slen  = arg[2].arg_ptr.arg_spat->spat_slen;
  690.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL &&
  691.         !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) &&
  692.         (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) )
  693.         sure |= CF_EQSURE;        /* (SUBST must be forced even */
  694.                         /* if we know it will work.) */
  695.         if (arg->arg_type != O_SUBST) {
  696.         arg[2].arg_ptr.arg_spat->spat_short = Nullstr;
  697.         arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */
  698.         }
  699.         sure |= CF_NESURE;        /* normally only sure if it fails */
  700.         if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST)
  701.         cmd->c_flags |= CF_FIRSTNEG;
  702.         if (context & 1) {        /* only sure if thing is false */
  703.         if (cmd->c_flags & CF_FIRSTNEG)
  704.             sure &= ~CF_NESURE;
  705.         else
  706.             sure &= ~CF_EQSURE;
  707.         }
  708.         else if (context & 2) {    /* only sure if thing is true */
  709.         if (cmd->c_flags & CF_FIRSTNEG)
  710.             sure &= ~CF_EQSURE;
  711.         else
  712.             sure &= ~CF_NESURE;
  713.         }
  714.         if (sure & (CF_EQSURE|CF_NESURE)) {    /* if we know anything*/
  715.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST)
  716.             opt = CFT_SCAN;
  717.         else
  718.             opt = CFT_ANCHOR;
  719.         if (sure == (CF_EQSURE|CF_NESURE)    /* really sure? */
  720.             && arg->arg_type == O_MATCH
  721.             && context & 4
  722.             && fliporflop == 1) {
  723.             spat_free(arg[2].arg_ptr.arg_spat);
  724.             arg[2].arg_ptr.arg_spat = Nullspat;    /* don't do twice */
  725.         }
  726.         else
  727.             cmd->c_spat = arg[2].arg_ptr.arg_spat;
  728.         cmd->c_flags |= sure;
  729.         }
  730.     }
  731.     }
  732.     else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE ||
  733.          arg->arg_type == O_SLT || arg->arg_type == O_SGT) {
  734.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  735.         if (arg[2].arg_type == A_SINGLE) {
  736.         /*SUPPRESS 594*/
  737.         char *junk = str_get(arg[2].arg_ptr.arg_str);
  738.  
  739.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  740.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_str);
  741.         cmd->c_slen  = cmd->c_short->str_cur+1;
  742.         switch (arg->arg_type) {
  743.         case O_SLT: case O_SGT:
  744.             sure |= CF_EQSURE;
  745.             cmd->c_flags |= CF_FIRSTNEG;
  746.             break;
  747.         case O_SNE:
  748.             cmd->c_flags |= CF_FIRSTNEG;
  749.             /* FALL THROUGH */
  750.         case O_SEQ:
  751.             sure |= CF_NESURE|CF_EQSURE;
  752.             break;
  753.         }
  754.         if (context & 1) {    /* only sure if thing is false */
  755.             if (cmd->c_flags & CF_FIRSTNEG)
  756.             sure &= ~CF_NESURE;
  757.             else
  758.             sure &= ~CF_EQSURE;
  759.         }
  760.         else if (context & 2) { /* only sure if thing is true */
  761.             if (cmd->c_flags & CF_FIRSTNEG)
  762.             sure &= ~CF_EQSURE;
  763.             else
  764.             sure &= ~CF_NESURE;
  765.         }
  766.         if (sure & (CF_EQSURE|CF_NESURE)) {
  767.             opt = CFT_STROP;
  768.             cmd->c_flags |= sure;
  769.         }
  770.         }
  771.     }
  772.     }
  773.     else if (arg->arg_type == O_EQ || arg->arg_type == O_NE ||
  774.          arg->arg_type == O_LE || arg->arg_type == O_GE ||
  775.          arg->arg_type == O_LT || arg->arg_type == O_GT) {
  776.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  777.         if (arg[2].arg_type == A_SINGLE) {
  778.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  779.         if (dowarn) {
  780.             STR *str = arg[2].arg_ptr.arg_str;
  781.  
  782.             if ((!str->str_nok && !looks_like_number(str)))
  783.             warn("Possible use of == on string value");
  784.         }
  785.         cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str));
  786.         cmd->c_slen = arg->arg_type;
  787.         sure |= CF_NESURE|CF_EQSURE;
  788.         if (context & 1) {    /* only sure if thing is false */
  789.             sure &= ~CF_EQSURE;
  790.         }
  791.         else if (context & 2) { /* only sure if thing is true */
  792.             sure &= ~CF_NESURE;
  793.         }
  794.         if (sure & (CF_EQSURE|CF_NESURE)) {
  795.             opt = CFT_NUMOP;
  796.             cmd->c_flags |= sure;
  797.         }
  798.         }
  799.     }
  800.     }
  801.     else if (arg->arg_type == O_ASSIGN &&
  802.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  803.          arg[1].arg_ptr.arg_stab == defstab &&
  804.          arg[2].arg_type == A_EXPR ) {
  805.     arg2 = arg[2].arg_ptr.arg_arg;
  806.     if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) {
  807.         opt = CFT_GETS;
  808.         cmd->c_stab = arg2[1].arg_ptr.arg_stab;
  809.         if (!(stab_io(arg2[1].arg_ptr.arg_stab)->flags & IOF_ARGV)) {
  810.         free_arg(arg2);
  811.         arg[2].arg_ptr.arg_arg = Nullarg;
  812.         free_arg(arg);
  813.         cmd->c_expr = Nullarg;
  814.         }
  815.     }
  816.     }
  817.     else if (arg->arg_type == O_CHOP &&
  818.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) {
  819.     opt = CFT_CHOP;
  820.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  821.     free_arg(arg);
  822.     cmd->c_expr = Nullarg;
  823.     }
  824.     if (context & 4)
  825.     opt |= CF_FLIP;
  826.     cmd->c_flags |= opt;
  827.  
  828.     if (cmd->c_flags & CF_FLIP) {
  829.     if (fliporflop == 1) {
  830.         arg = cmd->c_expr;    /* get back to O_FLIP arg */
  831.         New(110,arg[3].arg_ptr.arg_cmd, 1, CMD);
  832.         Copy(cmd, arg[3].arg_ptr.arg_cmd, 1, CMD);
  833.         New(111,arg[4].arg_ptr.arg_cmd,1,CMD);
  834.         Copy(cmd, arg[4].arg_ptr.arg_cmd, 1, CMD);
  835.         opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd);
  836.         arg->arg_len = 2;        /* this is a lie */
  837.     }
  838.     else {
  839.         if ((opt & CF_OPTIMIZE) == CFT_EVAL)
  840.         cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP;
  841.     }
  842.     }
  843. }
  844.  
  845. CMD *
  846. add_label(lbl,cmd)
  847. char *lbl;
  848. register CMD *cmd;
  849. {
  850.     if (cmd)
  851.     cmd->c_label = lbl;
  852.     return cmd;
  853. }
  854.  
  855. CMD *
  856. addcond(cmd, arg)
  857. register CMD *cmd;
  858. register ARG *arg;
  859. {
  860.     cmd->c_expr = arg;
  861.     cmd->c_flags |= CF_COND;
  862.     return cmd;
  863. }
  864.  
  865. CMD *
  866. addloop(cmd, arg)
  867. register CMD *cmd;
  868. register ARG *arg;
  869. {
  870.     void while_io();
  871.  
  872.     cmd->c_expr = arg;
  873.     cmd->c_flags |= CF_COND|CF_LOOP;
  874.  
  875.     if (!(cmd->c_flags & CF_INVERT))
  876.     while_io(cmd);        /* add $_ =, if necessary */
  877.  
  878.     if (cmd->c_type == C_BLOCK)
  879.     cmd->c_flags &= ~CF_COND;
  880.     else {
  881.     arg = cmd->ucmd.acmd.ac_expr;
  882.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  883.         cmd->c_flags &= ~CF_COND;  /* "do {} while" happens at least once */
  884.     if (arg && (arg->arg_flags & AF_DEPR) &&
  885.       (arg->arg_type == O_SUBR || arg->arg_type == O_DBSUBR) )
  886.         cmd->c_flags &= ~CF_COND;  /* likewise for "do subr() while" */
  887.     }
  888.     return cmd;
  889. }
  890.  
  891. CMD *
  892. invert(cmd)
  893. CMD *cmd;
  894. {
  895.     register CMD *targ = cmd;
  896.     if (targ->c_head)
  897.     targ = targ->c_head;
  898.     if (targ->c_flags & CF_DBSUB)
  899.     targ = targ->c_next;
  900.     targ->c_flags ^= CF_INVERT;
  901.     return cmd;
  902. }
  903.  
  904. yyerror(s)
  905. char *s;
  906. {
  907.     char tmpbuf[258];
  908.     char tmp2buf[258];
  909.     char *tname = tmpbuf;
  910.  
  911.     if (bufptr > oldoldbufptr && bufptr - oldoldbufptr < 200 &&
  912.       oldoldbufptr != oldbufptr && oldbufptr != bufptr) {
  913.     while (isSPACE(*oldoldbufptr))
  914.         oldoldbufptr++;
  915.     strncpy(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr);
  916.     tmp2buf[bufptr - oldoldbufptr] = '\0';
  917.     sprintf(tname,"next 2 tokens \"%s\"",tmp2buf);
  918.     }
  919.     else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 &&
  920.       oldbufptr != bufptr) {
  921.     while (isSPACE(*oldbufptr))
  922.         oldbufptr++;
  923.     strncpy(tmp2buf, oldbufptr, bufptr - oldbufptr);
  924.     tmp2buf[bufptr - oldbufptr] = '\0';
  925.     sprintf(tname,"next token \"%s\"",tmp2buf);
  926.     }
  927.     else if (yychar > 256)
  928.     tname = "next token ???";
  929.     else if (!yychar)
  930.     (void)strcpy(tname,"at EOF");
  931.     else if (yychar < 32)
  932.     (void)sprintf(tname,"next char ^%c",yychar+64);
  933.     else if (yychar == 127)
  934.     (void)strcpy(tname,"at EOF");
  935.     else
  936.     (void)sprintf(tname,"next char %c",yychar);
  937. #ifdef macintosh
  938.     (void)sprintf(buf, "# %s, %s\n", s, tname);
  939.     if (curcmd->c_line == multi_end && multi_start < multi_end)
  940.     sprintf(buf+strlen(buf),
  941.       "#  (Might be a runaway multi-line %c%c string starting on line %d)\n",
  942.       multi_open,multi_close,multi_start);
  943.     (void)sprintf(buf+strlen(buf),
  944.       "File %s; Line %d\n",
  945.       stab_val(curcmd->c_filestab)->str_ptr,curcmd->c_line);
  946. #else
  947.     (void)sprintf(buf, "%s in file %s at line %d, %s\n",
  948.       s,stab_val(curcmd->c_filestab)->str_ptr,curcmd->c_line,tname);
  949.     if (curcmd->c_line == multi_end && multi_start < multi_end)
  950.     sprintf(buf+strlen(buf),
  951.       "  (Might be a runaway multi-line %c%c string starting on line %d)\n",
  952.       multi_open,multi_close,multi_start);
  953. #endif
  954.     if (in_eval)
  955.     str_cat(stab_val(stabent("@",TRUE)),buf);
  956.     else
  957.     fputs(buf,stderr);
  958.     if (++error_count >= 10)
  959.     fatal("%s has too many errors.\n",
  960.     stab_val(curcmd->c_filestab)->str_ptr);
  961. }
  962.  
  963. void
  964. while_io(cmd)
  965. register CMD *cmd;
  966. {
  967.     register ARG *arg = cmd->c_expr;
  968.     STAB *asgnstab;
  969.  
  970.     /* hoist "while (<channel>)" up into command block */
  971.  
  972.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) {
  973.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  974.     cmd->c_flags |= CFT_GETS;    /* and set it to do the input */
  975.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  976.     if (stab_io(arg[1].arg_ptr.arg_stab)->flags & IOF_ARGV) {
  977.         cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$_ =" */
  978.            stab2arg(A_LVAL,defstab), arg, Nullarg));
  979.     }
  980.     else {
  981.         free_arg(arg);
  982.         cmd->c_expr = Nullarg;
  983.     }
  984.     }
  985.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) {
  986.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  987.     cmd->c_flags |= CFT_INDGETS;    /* and set it to do the input */
  988.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  989.     free_arg(arg);
  990.     cmd->c_expr = Nullarg;
  991.     }
  992.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) {
  993.     if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY)
  994.         asgnstab = cmd->c_stab;
  995.     else
  996.         asgnstab = defstab;
  997.     cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$foo =" */
  998.        stab2arg(A_LVAL,asgnstab), arg, Nullarg));
  999.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1000.     }
  1001. }
  1002.  
  1003. CMD *
  1004. wopt(cmd)
  1005. register CMD *cmd;
  1006. {
  1007.     register CMD *tail;
  1008.     CMD *newtail;
  1009.     register int i;
  1010.  
  1011.     if (cmd->c_expr && (cmd->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  1012.     opt_arg(cmd,1, cmd->c_type == C_EXPR);
  1013.  
  1014.     while_io(cmd);        /* add $_ =, if necessary */
  1015.  
  1016.     /* First find the end of the true list */
  1017.  
  1018.     tail = cmd->ucmd.ccmd.cc_true;
  1019.     if (tail == Nullcmd)
  1020.     return cmd;
  1021.     New(112,newtail, 1, CMD);    /* guaranteed continue */
  1022.     for (;;) {
  1023.     /* optimize "next" to point directly to continue block */
  1024.     if (tail->c_type == C_EXPR &&
  1025.         tail->ucmd.acmd.ac_expr &&
  1026.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1027.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1028.          (cmd->c_label &&
  1029.           strEQ(cmd->c_label,
  1030.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1031.     {
  1032.         arg_free(tail->ucmd.acmd.ac_expr);
  1033.         tail->ucmd.acmd.ac_expr = Nullarg;
  1034.         tail->c_type = C_NEXT;
  1035.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1036.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1037.         else
  1038.         tail->ucmd.ccmd.cc_alt = newtail;
  1039.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1040.     }
  1041.     else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1042.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1043.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1044.         else
  1045.         tail->ucmd.ccmd.cc_alt = newtail;
  1046.     }
  1047.     else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1048.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1049.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1050.             if (!tail->ucmd.scmd.sc_next[i])
  1051.             tail->ucmd.scmd.sc_next[i] = cmd->ucmd.ccmd.cc_alt;
  1052.         }
  1053.         else {
  1054.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1055.             if (!tail->ucmd.scmd.sc_next[i])
  1056.             tail->ucmd.scmd.sc_next[i] = newtail;
  1057.         }
  1058.     }
  1059.  
  1060.     if (!tail->c_next)
  1061.         break;
  1062.     tail = tail->c_next;
  1063.     }
  1064.  
  1065.     /* if there's a continue block, link it to true block and find end */
  1066.  
  1067.     if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1068. #ifdef macintosh
  1069.     /* Work around a code generation bug in MPW C 3.2 */
  1070.     tail->c_next = cmd->ucmd.ccmd.cc_alt;
  1071.     tail = cmd->ucmd.ccmd.cc_alt;
  1072. #else
  1073.     tail->c_next = cmd->ucmd.ccmd.cc_alt;
  1074.     tail = tail->c_next;
  1075. #endif
  1076.     for (;;) {
  1077.         /* optimize "next" to point directly to continue block */
  1078.         if (tail->c_type == C_EXPR &&
  1079.         tail->ucmd.acmd.ac_expr &&
  1080.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1081.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1082.          (cmd->c_label &&
  1083.           strEQ(cmd->c_label,
  1084.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1085.         {
  1086.         arg_free(tail->ucmd.acmd.ac_expr);
  1087.         tail->ucmd.acmd.ac_expr = Nullarg;
  1088.         tail->c_type = C_NEXT;
  1089.         tail->ucmd.ccmd.cc_alt = newtail;
  1090.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1091.         }
  1092.         else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1093.         tail->ucmd.ccmd.cc_alt = newtail;
  1094.         }
  1095.         else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1096.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1097.             if (!tail->ucmd.scmd.sc_next[i])
  1098.             tail->ucmd.scmd.sc_next[i] = newtail;
  1099.         }
  1100.  
  1101.         if (!tail->c_next)
  1102.         break;
  1103.         tail = tail->c_next;
  1104.     }
  1105.     /*SUPPRESS 530*/
  1106.     for ( ; tail->c_next; tail = tail->c_next) ;
  1107.     }
  1108.  
  1109.     /* Here's the real trick: link the end of the list back to the beginning,
  1110.      * inserting a "last" block to break out of the loop.  This saves one or
  1111.      * two procedure calls every time through the loop, because of how cmd_exec
  1112.      * does tail recursion.
  1113.      */
  1114.  
  1115.     tail->c_next = newtail;
  1116.     tail = newtail;
  1117.     if (!cmd->ucmd.ccmd.cc_alt)
  1118.     cmd->ucmd.ccmd.cc_alt = tail;    /* every loop has a continue now */
  1119.  
  1120. #ifndef lint
  1121.     (void)bcopy((char *)cmd, (char *)tail, sizeof(CMD));
  1122. #endif
  1123.     tail->c_type = C_EXPR;
  1124.     tail->c_flags ^= CF_INVERT;        /* turn into "last unless" */
  1125.     tail->c_next = tail->ucmd.ccmd.cc_true;    /* loop directly back to top */
  1126.     tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg);
  1127.     tail->ucmd.acmd.ac_stab = Nullstab;
  1128.     return cmd;
  1129. }
  1130.  
  1131. CMD *
  1132. over(eachstab,cmd)
  1133. STAB *eachstab;
  1134. register CMD *cmd;
  1135. {
  1136.     /* hoist "for $foo (@bar)" up into command block */
  1137.  
  1138.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1139.     cmd->c_flags |= CFT_ARRAY;        /* and set it to do the iteration */
  1140.     cmd->c_stab = eachstab;
  1141.     cmd->c_short = Str_new(23,0);    /* just to save a field in struct cmd */
  1142.     cmd->c_short->str_u.str_useful = -1;
  1143.  
  1144.     return cmd;
  1145. }
  1146.  
  1147. cmd_free(cmd)
  1148. register CMD *cmd;
  1149. {
  1150.     register CMD *tofree;
  1151.     register CMD *head = cmd;
  1152.  
  1153.     while (cmd) {
  1154.     if (cmd->c_type != C_WHILE) {    /* WHILE block is duplicated */
  1155.         if (cmd->c_label) {
  1156.         Safefree(cmd->c_label);
  1157.         cmd->c_label = Nullch;
  1158.         }
  1159.         if (cmd->c_short) {
  1160.         str_free(cmd->c_short);
  1161.         cmd->c_short = Nullstr;
  1162.         }
  1163.         if (cmd->c_expr) {
  1164.         arg_free(cmd->c_expr);
  1165.         cmd->c_expr = Nullarg;
  1166.         }
  1167.     }
  1168.     switch (cmd->c_type) {
  1169.     case C_WHILE:
  1170.     case C_BLOCK:
  1171.     case C_ELSE:
  1172.     case C_IF:
  1173.         if (cmd->ucmd.ccmd.cc_true) {
  1174.         cmd_free(cmd->ucmd.ccmd.cc_true);
  1175.         cmd->ucmd.ccmd.cc_true = Nullcmd;
  1176.         }
  1177.         break;
  1178.     case C_EXPR:
  1179.         if (cmd->ucmd.acmd.ac_expr) {
  1180.         arg_free(cmd->ucmd.acmd.ac_expr);
  1181.         cmd->ucmd.acmd.ac_expr = Nullarg;
  1182.         }
  1183.         break;
  1184.     }
  1185.     tofree = cmd;
  1186.     cmd = cmd->c_next;
  1187.     if (tofree != head)        /* to get Saber to shut up */
  1188.         Safefree(tofree);
  1189.     if (cmd && cmd == head)        /* reached end of while loop */
  1190.         break;
  1191.     }
  1192.     Safefree(head);
  1193. }
  1194.  
  1195. arg_free(arg)
  1196. register ARG *arg;
  1197. {
  1198.     register int i;
  1199.  
  1200.     for (i = 1; i <= arg->arg_len; i++) {
  1201.     switch (arg[i].arg_type & A_MASK) {
  1202.     case A_NULL:
  1203.         if (arg->arg_type == O_TRANS) {
  1204.         Safefree(arg[i].arg_ptr.arg_cval);
  1205.         arg[i].arg_ptr.arg_cval = Nullch;
  1206.         }
  1207.         break;
  1208.     case A_LEXPR:
  1209.         if (arg->arg_type == O_AASSIGN &&
  1210.           arg[i].arg_ptr.arg_arg->arg_type == O_LARRAY) {
  1211.         char *name = 
  1212.           stab_name(arg[i].arg_ptr.arg_arg[1].arg_ptr.arg_stab);
  1213.  
  1214.         if (strnEQ("_GEN_",name, 5))    /* array for foreach */
  1215.             hdelete(defstash,name,strlen(name));
  1216.         }
  1217.         /* FALL THROUGH */
  1218.     case A_EXPR:
  1219.         arg_free(arg[i].arg_ptr.arg_arg);
  1220.         arg[i].arg_ptr.arg_arg = Nullarg;
  1221.         break;
  1222.     case A_CMD:
  1223.         cmd_free(arg[i].arg_ptr.arg_cmd);
  1224.         arg[i].arg_ptr.arg_cmd = Nullcmd;
  1225.         break;
  1226.     case A_WORD:
  1227.     case A_STAB:
  1228.     case A_LVAL:
  1229.     case A_READ:
  1230.     case A_GLOB:
  1231.     case A_ARYLEN:
  1232.     case A_LARYLEN:
  1233.     case A_ARYSTAB:
  1234.     case A_LARYSTAB:
  1235.         break;
  1236.     case A_SINGLE:
  1237.     case A_DOUBLE:
  1238.     case A_BACKTICK:
  1239.         str_free(arg[i].arg_ptr.arg_str);
  1240.         arg[i].arg_ptr.arg_str = Nullstr;
  1241.         break;
  1242.     case A_SPAT:
  1243.         spat_free(arg[i].arg_ptr.arg_spat);
  1244.         arg[i].arg_ptr.arg_spat = Nullspat;
  1245.         break;
  1246.     }
  1247.     }
  1248.     free_arg(arg);
  1249. }
  1250.  
  1251. spat_free(spat)
  1252. register SPAT *spat;
  1253. {
  1254.     register SPAT *sp;
  1255.     HENT *entry;
  1256.  
  1257.     if (spat->spat_runtime) {
  1258.     arg_free(spat->spat_runtime);
  1259.     spat->spat_runtime = Nullarg;
  1260.     }
  1261.     if (spat->spat_repl) {
  1262.     arg_free(spat->spat_repl);
  1263.     spat->spat_repl = Nullarg;
  1264.     }
  1265.     if (spat->spat_short) {
  1266.     str_free(spat->spat_short);
  1267.     spat->spat_short = Nullstr;
  1268.     }
  1269.     if (spat->spat_regexp) {
  1270.     regfree(spat->spat_regexp);
  1271.     spat->spat_regexp = Null(REGEXP*);
  1272.     }
  1273.  
  1274.     /* now unlink from spat list */
  1275.  
  1276.     for (entry = defstash->tbl_array['_']; entry; entry = entry->hent_next) {
  1277.     register HASH *stash;
  1278.     STAB *stab = (STAB*)entry->hent_val;
  1279.  
  1280.     if (!stab)
  1281.         continue;
  1282.     stash = stab_hash(stab);
  1283.     if (!stash || stash->tbl_spatroot == Null(SPAT*))
  1284.         continue;
  1285.     if (stash->tbl_spatroot == spat)
  1286.         stash->tbl_spatroot = spat->spat_next;
  1287.     else {
  1288.         for (sp = stash->tbl_spatroot;
  1289.           sp && sp->spat_next != spat;
  1290.           sp = sp->spat_next)
  1291.         /*SUPPRESS 530*/
  1292.         ;
  1293.         if (sp)
  1294.         sp->spat_next = spat->spat_next;
  1295.     }
  1296.     }
  1297.     Safefree(spat);
  1298. }
  1299.  
  1300. /* Recursively descend a command sequence and push the address of any string
  1301.  * that needs saving on recursion onto the tosave array.
  1302.  */
  1303.  
  1304. static int
  1305. cmd_tosave(cmd,willsave)
  1306. register CMD *cmd;
  1307. int willsave;                /* willsave passes down the tree */
  1308. {
  1309.     register CMD *head = cmd;
  1310.     int shouldsave = FALSE;        /* shouldsave passes up the tree */
  1311.     int tmpsave;
  1312.     register CMD *lastcmd = Nullcmd;
  1313.  
  1314.     while (cmd) {
  1315.     if (cmd->c_expr)
  1316.         shouldsave |= arg_tosave(cmd->c_expr,willsave);
  1317.     switch (cmd->c_type) {
  1318.     case C_WHILE:
  1319.         if (cmd->ucmd.ccmd.cc_true) {
  1320.         tmpsave = cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1321.  
  1322.         /* Here we check to see if the temporary array generated for
  1323.          * a foreach needs to be localized because of recursion.
  1324.          */
  1325.         if (tmpsave && (cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) {
  1326.             if (lastcmd &&
  1327.               lastcmd->c_type == C_EXPR &&
  1328.               lastcmd->c_expr) {
  1329.             ARG *arg = lastcmd->c_expr;
  1330.  
  1331.             if (arg->arg_type == O_ASSIGN &&
  1332.                 arg[1].arg_type == A_LEXPR &&
  1333.                 arg[1].arg_ptr.arg_arg->arg_type == O_LARRAY &&
  1334.                 strnEQ("_GEN_",
  1335.                   stab_name(
  1336.                 arg[1].arg_ptr.arg_arg[1].arg_ptr.arg_stab),
  1337.                   5)) {    /* array generated for foreach */
  1338.                 (void)localize(arg);
  1339.             }
  1340.             }
  1341.  
  1342.             /* in any event, save the iterator */
  1343.  
  1344.             (void)apush(tosave,cmd->c_short);
  1345.         }
  1346.         shouldsave |= tmpsave;
  1347.         }
  1348.         break;
  1349.     case C_BLOCK:
  1350.     case C_ELSE:
  1351.     case C_IF:
  1352.         if (cmd->ucmd.ccmd.cc_true)
  1353.         shouldsave |= cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1354.         break;
  1355.     case C_EXPR:
  1356.         if (cmd->ucmd.acmd.ac_expr)
  1357.         shouldsave |= arg_tosave(cmd->ucmd.acmd.ac_expr,willsave);
  1358.         break;
  1359.     }
  1360.     lastcmd = cmd;
  1361.     cmd = cmd->c_next;
  1362.     if (cmd && cmd == head)        /* reached end of while loop */
  1363.         break;
  1364.     }
  1365.     return shouldsave;
  1366. }
  1367.  
  1368. static int
  1369. arg_tosave(arg,willsave)
  1370. register ARG *arg;
  1371. int willsave;
  1372. {
  1373.     register int i;
  1374.     int shouldsave = FALSE;
  1375.  
  1376.     for (i = arg->arg_len; i >= 1; i--) {
  1377.     switch (arg[i].arg_type & A_MASK) {
  1378.     case A_NULL:
  1379.         break;
  1380.     case A_LEXPR:
  1381.     case A_EXPR:
  1382.         shouldsave |= arg_tosave(arg[i].arg_ptr.arg_arg,shouldsave);
  1383.         break;
  1384.     case A_CMD:
  1385.         shouldsave |= cmd_tosave(arg[i].arg_ptr.arg_cmd,shouldsave);
  1386.         break;
  1387.     case A_WORD:
  1388.     case A_STAB:
  1389.     case A_LVAL:
  1390.     case A_READ:
  1391.     case A_GLOB:
  1392.     case A_ARYLEN:
  1393.     case A_SINGLE:
  1394.     case A_DOUBLE:
  1395.     case A_BACKTICK:
  1396.         break;
  1397.     case A_SPAT:
  1398.         shouldsave |= spat_tosave(arg[i].arg_ptr.arg_spat);
  1399.         break;
  1400.     }
  1401.     }
  1402.     switch (arg->arg_type) {
  1403.     case O_RETURN:
  1404.     saw_return = TRUE;
  1405.     break;
  1406.     case O_EVAL:
  1407.     case O_SUBR:
  1408.     shouldsave = TRUE;
  1409.     break;
  1410.     }
  1411.     if (willsave)
  1412.     (void)apush(tosave,arg->arg_ptr.arg_str);
  1413.     return shouldsave;
  1414. }
  1415.  
  1416. static int
  1417. spat_tosave(spat)
  1418. register SPAT *spat;
  1419. {
  1420.     int shouldsave = FALSE;
  1421.  
  1422.     if (spat->spat_runtime)
  1423.     shouldsave |= arg_tosave(spat->spat_runtime,FALSE);
  1424.     if (spat->spat_repl) {
  1425.     shouldsave |= arg_tosave(spat->spat_repl,FALSE);
  1426.     }
  1427.  
  1428.     return shouldsave;
  1429. }
  1430.  
  1431.